#include "httpclient.h"

#include <cstring>
#include <iostream>
#include <strstream>

#ifdef Q_OS_WIN
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
#else
//#include <arpa/inet.h>
//#include <netinet/in.h>
//#include <sys/socket.h>
//#include <unistd.h>
//#include <fcntl.h>

#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>

#endif



HttpClient::HttpClient()
:m_sock(-1)
{
#ifdef Q_OS_WIN
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
        qDebug() << "Failed to initialize winsock" ;
    }
#endif

}

HttpClient::~HttpClient()
{
#ifdef Q_OS_WIN
    WSACleanup();
#endif

    if (m_sock != -1) {
        close(m_sock);
    }

}

void HttpClient::setUrl(const std::string& host, int port)
{
    m_host = host;
    m_port = port;
}


bool HttpClient::get(const std::string& path) {
    return sendHttpRequest("GET", path);
}

bool HttpClient::post(const std::string& path, const std::string& data) {
    return sendHttpRequest("POST", path, data);
}

bool HttpClient::put(const std::string& path, const std::string& data) {
    return sendHttpRequest("PUT", path, data);
}

bool HttpClient::del(const std::string& path) {
    return sendHttpRequest("DELETE", path);
}

bool HttpClient::head(const std::string& path) {
    return sendHttpRequest("HEAD", path);
}

bool HttpClient::connectToServer() {
    m_sock = socket(AF_INET, SOCK_STREAM, 0);
    if (m_sock == -1) {
        return false;
    }

    struct hostent* server = gethostbyname(m_host.c_str());
    if (server == nullptr) {
        return false;
    }

    struct sockaddr_in server_address{};
    memset(&server_address, 0, sizeof(server_address));
    server_address.sin_family = AF_INET;
    server_address.sin_port = htons(m_port);
    memcpy(&server_address.sin_addr.s_addr, server->h_addr, server->h_length);

    if (connect(m_sock, (struct sockaddr*)&server_address, sizeof(server_address)) < 0) {
        return false;
    }

    return true;
}

bool HttpClient::sendHttpRequest(const std::string& method, const std::string& path, const std::string& data ) {
    if(!connectToServer()){
        return false;
    }

    std::ostringstream requestStream ;
    requestStream  << method << " " << path << " HTTP/1.1\r\n";
    requestStream  << "Host: " << m_host << "\r\n";
    requestStream  << "Connection: close\r\n";

    if (!data.empty()) {
        requestStream  << "Content-Length: " << data.length() << "\r\n";
    }

    for (const auto& header : m_headers) {
        requestStream  << header << "\r\n";
    }

    requestStream  << "\r\n";

    if (!data.empty()) {
        requestStream  << data;
    }

    std::string request = requestStream .str();

    if (send(m_sock, request.c_str(), request.length(),0) < 0) {
        return false;
    }

    std::string response;
    if(!readHttpResponse(response)){
        return false;
    }
    parseResponse(response);

    return true;
}

bool HttpClient::readHttpResponse(std::string& response) {
    char buffer[1024];
    ssize_t bytesRead;

    while ((bytesRead = recv(m_sock, buffer, sizeof(buffer),0)) > 0) {
        response.append(buffer, bytesRead);
    }


    return true;
}


void HttpClient::addHeader(const std::string& header) {
    m_headers.push_back(header);
}

std::vector<std::string> HttpClient::getHeaders() const {
    return m_headers;
}

std::string HttpClient::getBody() const {
    return m_body;
}



void HttpClient::parseResponse(const std::string& response) {
    //http协议的头部和请求体之间用\r\n\r\n分隔
    size_t pos = 0;
    size_t eol = response.find("\r\n\r\n", pos);
    if (eol == std::string::npos) {
        return ;
    }
    std::string headStr = response.substr(pos, eol - pos);
    m_body = response.substr(eol + 4);

    std::istringstream head(headStr);
    std::string headerLine;

    while (std::getline(head, headerLine) && !headerLine.empty()) {
        m_headers.push_back(headerLine);
    }
}

